
#include <fstream>
#include <iostream>
#include <stdlib.h>
#include <mpi.h>
#include "usual.hpp"
#include "functions.hpp"
#include <time.h>

using namespace std;
using namespace Magick;

Usual::Usual(const char* filename)
{
    cout << "filename: " << filename << endl;
    if(!read_inputFile(filename))
        MPI::COMM_WORLD.Abort(-2);

}

Usual::~Usual()
{
    for(list<Magick::Image*>::iterator it = pictures.begin(); it != pictures.end(); ++ it)
        delete *it;
}

double Usual::read_inputFile(const char* filename)
{
    double initTime;

    std::ifstream f(filename, std::ios::in);

    if(f)
    {
        string l;
        unsigned long p = 0;

        //get matrix size
        getline(f, l);
        p = nextWord(l);
        matrix_size = atoi(l.substr(p).c_str());

        //get matrix
        matrix = new double *[matrix_size];
        for(int i = 0; i< matrix_size; ++i)
        {
            matrix[i] = new double[matrix_size];
            getline(f, l);
            p = 0;
            for(int j =0; j< matrix_size; ++j)
            {
                p = nextWord(l, p);
                matrix[i][j] = atof(getWord(l, p).c_str());//atof(l.substr(p).c_str());
            }
        }

        //get read_path
        getline(f,l);
        p = nextWord(l);
        read_path = l.substr(p) +"/";

        //get write_path
        getline(f,l);
        p = nextWord(l);
        write_path = l.substr(p)+"/";

        //get picture's name list
        getline(f,l);
        p = nextWord(l);

        string * pic = new string(l.substr(p));
        pictures_string = list<string>(1,*pic);

        while(! f.eof())
        {
            getline(f,l);
            p = nextWord(l);
            string *pic = new string(l.substr(p));
            if(pic->length() > 0) // = if( (*pic).length() > 0 )
                pictures_string.push_back(*pic);
        }

        cout << "file correctly loaded" << endl;
        initTime = MPI::Wtime();
        // chargement des images en mémoire
        pictures = list<Magick::Image*>();
        for(list<string>::iterator it = pictures_string.begin(); it != pictures_string.end(); ++it)
        {
            //string im = *it;
            cout << " Image : "<< *it << endl;
            try{
                Magick::Image* lImage = new Magick::Image(read_path + *it +".png");
                pictures.push_back(lImage);
            } catch(Error &err){
                Magick::Image* lImage = new Magick::Image(read_path + *it +".jpg");
                pictures.push_back(lImage);
            }
        }

        readTime = MPI::Wtime() - initTime;

        cout << "Le temps réel requis pour la lecture des images = " << readTime << " secondes" << endl;
        cout << "Pictures correctly loaded"<< endl ;

        return readTime;
    } else { // file opening failed
        cerr << "The file failed to open." << endl
             << "Maybe the input argument was wrong" << endl <<endl;
        return 0;
    }
}

/**
 * Warning, this methode doesn't remove the first element from the list
 */
string& Usual::next_picture_string(void){
    return pictures_string.back();
}
 void Usual::pop_picture_string(void){
     pictures_string.pop_back();
 }

Magick::Image& Usual::next_picture(void)
{
    if(pictures.size() > 0)
        return * (pictures.back());
}

Magick::Image Usual::pop_picture(void)
{//*
    Magick::Image ret(*pictures.back());
    //delete pictures.back();
    pictures.pop_back();
    return ret;
    //*/
}

// Operateurs de sortie: <<
// pour l'affichage
ostream& operator<< (ostream& o, Usual& a)
{
    o << endl;
    o << "-------------------------------------------" << endl;
    o << "--------------Actual Datas-----------------" << endl;
    o << "-------------------------------------------" << endl;
    o << "Nombre d'image à traiter : " << a.pictures_string.size() << endl;
    o << "taille de la matrice :" << a.matrix_size << " par " << a.matrix_size << endl;
    o << "matrice : (display number as float instead of double)" << endl;
    o.setf(ios::fixed,ios::floatfield);
    for(int i = 0; i < a.matrix_size ; ++i){
        for(int j = 0; j< a.matrix_size; ++j)
        {
            o << a.matrix[i][j] << " ";
        }
        o << endl;
    }
    o << endl<<endl;


    try
    {
        if(a.pictures.size() == 0)
            o << "no more pictures" <<endl;
        else
            for(list<Magick::Image*>::iterator it = a.pictures.begin(); it != a.pictures.end(); ++it)
            {
                cout << (*it)->fileName() << endl;
                o << "Format de l'image: " << (*it)->magick() << endl;
                o << "Dimension de l'image: " << (*it)->rows() << "x"
                     << (*it)->columns() << " pixels" << endl;
                o << "Size d'un Quantum: " << sizeof(Quantum) << " octets" << endl << endl;
            }
    }
    catch(Error& lError)
    {
        abort(lError.what());
    }

	return o;
}
